/**
 * utils/cryptoUtil.js
 *
 * 前端加解密工具：支持 AES-GCM 对称加密、RSA-OAEP 公私钥加解密
 */

const CryptoUtil = (function () {
  const AES_ALGO = { name: "AES-GCM", length: 256 };
  const RSA_ALGO = {
    name: "RSA-OAEP",
    modulusLength: 2048,
    publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
    hash: "SHA-256"
  };
  const IV_LENGTH = 12;

  // ========= Base64 编码/解码 =========
  function bufToBase64(buffer) {
    return btoa(String.fromCharCode(...new Uint8Array(buffer)));
  }
  function base64ToBuf(base64) {
    const binary = atob(base64);
    const len = binary.length;
    const bytes = new Uint8Array(len);
    for (let i = 0; i < len; i++) bytes[i] = binary.charCodeAt(i);
    return bytes.buffer;
  }

  // ========= AES 部分 =========
  async function generateAESKeyBase64() {
    const key = await crypto.subtle.generateKey(AES_ALGO, true, ["encrypt", "decrypt"]);
    const raw = await crypto.subtle.exportKey("raw", key);
    return bufToBase64(raw);
  }

  async function importAESKey(base64Key) {
    return crypto.subtle.importKey("raw", base64ToBuf(base64Key), AES_ALGO, true, ["encrypt", "decrypt"]);
  }

  async function encryptAES(plainText, base64Key) {
    const key = await importAESKey(base64Key);
    const iv = crypto.getRandomValues(new Uint8Array(IV_LENGTH));
    const encoder = new TextEncoder();
    const encrypted = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, encoder.encode(plainText));
    const ivCipher = new Uint8Array(iv.length + encrypted.byteLength);
    ivCipher.set(iv);
    ivCipher.set(new Uint8Array(encrypted), iv.length);
    return bufToBase64(ivCipher.buffer);
  }

  async function decryptAES(base64Cipher, base64Key) {
    const key = await importAESKey(base64Key);
    const data = new Uint8Array(base64ToBuf(base64Cipher));
    const iv = data.slice(0, IV_LENGTH);
    const cipher = data.slice(IV_LENGTH);
    const decrypted = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, key, cipher);
    return new TextDecoder().decode(decrypted);
  }

  // ========= RSA 部分 =========
  async function generateRSAKeyPair() {
    const keyPair = await crypto.subtle.generateKey(RSA_ALGO, true, ["encrypt", "decrypt"]);
    const pubKey = await crypto.subtle.exportKey("spki", keyPair.publicKey);
    const priKey = await crypto.subtle.exportKey("pkcs8", keyPair.privateKey);
    return {
      publicKey: bufToBase64(pubKey),
      privateKey: bufToBase64(priKey)
    };
  }

  async function importRSAPublicKey(base64Key) {
    return crypto.subtle.importKey("spki", base64ToBuf(base64Key), RSA_ALGO, true, ["encrypt"]);
  }

  async function importRSAPrivateKey(base64Key) {
    return crypto.subtle.importKey("pkcs8", base64ToBuf(base64Key), RSA_ALGO, true, ["decrypt"]);
  }

  async function encryptRSA(plainText, base64PublicKey) {
    const key = await importRSAPublicKey(base64PublicKey);
    const encoder = new TextEncoder();
    const encrypted = await crypto.subtle.encrypt({ name: "RSA-OAEP" }, key, encoder.encode(plainText));
    return bufToBase64(encrypted);
  }

  async function decryptRSA(base64Cipher, base64PrivateKey) {
    const key = await importRSAPrivateKey(base64PrivateKey);
    const decrypted = await crypto.subtle.decrypt({ name: "RSA-OAEP" }, key, base64ToBuf(base64Cipher));
    return new TextDecoder().decode(decrypted);
  }

  // ========= 文件保存工具 =========
  function saveToFile(filename, content) {
    const blob = new Blob([content], { type: "text/plain;charset=utf-8" });
    const link = document.createElement("a");
    link.href = URL.createObjectURL(blob);
    link.download = filename;
    link.click();
    URL.revokeObjectURL(link.href);
  }

  // ========= 导出 API =========
  return {
    // AES
    generateAESKeyBase64,
    importAESKey,
    encryptAES,
    decryptAES,
    // RSA
    generateRSAKeyPair,
    importRSAPublicKey,
    importRSAPrivateKey,
    encryptRSA,
    decryptRSA,
    // 文件操作
    saveToFile
  };
})();

export default CryptoUtil;

/**
 * ========== 使用示例 ==========
 * import CryptoUtil from '@/utils/cryptoUtil'
 *
 * // 生成 AES 密钥
 * const aesKey = await CryptoUtil.generateAESKeyBase64()
 * const cipher = await CryptoUtil.encryptAES("hello", aesKey)
 * const plain = await CryptoUtil.decryptAES(cipher, aesKey)
 *
 * // 生成 RSA 密钥对
 * const { publicKey, privateKey } = await CryptoUtil.generateRSAKeyPair()
 * const rsaCipher = await CryptoUtil.encryptRSA("secret message", publicKey)
 * const rsaPlain = await CryptoUtil.decryptRSA(rsaCipher, privateKey)
 *
 * // 保存密钥为文件
 * CryptoUtil.saveToFile('publicKey.pem', publicKey)
 */


 /**
  * utils/symmetric.js
  *
  * 基于 Web Crypto (SubtleCrypto) 的 AES-GCM 对称加密工具
  * - 生成 256-bit AES 密钥（返回 Base64 编码）
  * - 导出 / 导入 Base64 编码的密钥
  * - encrypt(plain, base64Key) -> 返回 Base64( iv || cipher )
  * - decrypt(base64CipherWithIv, base64Key) -> 返回明文字符串
  *
  * 说明：
  *  - 使用 AES-GCM，iv 长度 12 bytes（96 bits），这是推荐值
  *  - 密文格式：把 iv（12 bytes）放在最前面，然后拼接 ciphertext，最后整体 base64 编码
  *  - 需要运行在支持 Web Crypto 的浏览器环境
  */

 const SymmetricUtil = (function () {
   const algo = { name: "AES-GCM", length: 256 };
   const ivLength = 12; // bytes (96 bits) 推荐用于 GCM

   // ====== base64 编解码 helpers ======
   function bufToBase64(buffer) {
     const bytes = new Uint8Array(buffer);
     let binary = "";
     for (let i = 0; i < bytes.byteLength; i++) {
       binary += String.fromCharCode(bytes[i]);
     }
     return btoa(binary);
   }

   function base64ToBuf(base64) {
     const binary = atob(base64);
     const len = binary.length;
     const bytes = new Uint8Array(len);
     for (let i = 0; i < len; i++) {
       bytes[i] = binary.charCodeAt(i);
     }
     return bytes.buffer;
   }

   // ====== key 导入/导出 ======
   async function generateKeyBase64() {
     // 生成 CryptoKey 并导出为 base64
     const key = await window.crypto.subtle.generateKey(algo, true, ["encrypt", "decrypt"]);
     const raw = await window.crypto.subtle.exportKey("raw", key);
     return bufToBase64(raw);
   }

   async function importKeyFromBase64(base64Key) {
     const raw = base64ToBuf(base64Key);
     return await window.crypto.subtle.importKey("raw", raw, algo, true, ["encrypt", "decrypt"]);
   }

   async function exportKeyToBase64(cryptoKey) {
     const raw = await window.crypto.subtle.exportKey("raw", cryptoKey);
     return bufToBase64(raw);
   }

   // ====== AES-GCM 加密/解密 ======
   /**
    * 加密
    * @param {string} plainText - 明文字符串
    * @param {string} base64Key - Base64 编码的 AES 密钥
    * @returns {Promise<string>} Base64(iv + cipher)
    */
   async function encrypt(plainText, base64Key) {
     if (!plainText) return "";
     const key = await importKeyFromBase64(base64Key);
     const iv = window.crypto.getRandomValues(new Uint8Array(ivLength));
     const enc = new TextEncoder();
     const plainBuf = enc.encode(plainText);

     const cipherBuf = await window.crypto.subtle.encrypt(
       { name: "AES-GCM", iv: iv },
       key,
       plainBuf
     );

     // 拼接 iv + cipher
     const ivAndCipher = new Uint8Array(ivLength + cipherBuf.byteLength);
     ivAndCipher.set(iv, 0);
     ivAndCipher.set(new Uint8Array(cipherBuf), ivLength);
     return bufToBase64(ivAndCipher.buffer);
   }

   /**
    * 解密
    * @param {string} base64IvAndCipher - Base64(iv + cipher)
    * @param {string} base64Key - Base64 编码的 AES 密钥
    * @returns {Promise<string>} 明文字符串
    */
   async function decrypt(base64IvAndCipher, base64Key) {
     if (!base64IvAndCipher) return "";
     const key = await importKeyFromBase64(base64Key);
     const ivAndCipherBuf = base64ToBuf(base64IvAndCipher);
     const arr = new Uint8Array(ivAndCipherBuf);
     const iv = arr.slice(0, ivLength);
     const cipher = arr.slice(ivLength);
     const plainBuf = await window.crypto.subtle.decrypt(
       { name: "AES-GCM", iv: iv },
       key,
       cipher
     );
     const dec = new TextDecoder();
     return dec.decode(plainBuf);
   }

   // ====== 便捷：把 base64Key 保存到 localStorage（可选辅助） ======
   function saveKeyToLocalStorage(name, base64Key) {
     if (!name || !base64Key) return false;
     try {
       localStorage.setItem(name, base64Key);
       return true;
     } catch (e) {
       return false;
     }
   }

   function loadKeyFromLocalStorage(name) {
     return localStorage.getItem(name);
   }

   // ====== 导出 API ======
   return {
     generateKeyBase64,    // () => Promise<string>
     importKeyFromBase64,  // (base64Key) => Promise<CryptoKey>
     exportKeyToBase64,    // (CryptoKey) => Promise<string>
     encrypt,              // (plainText, base64Key) => Promise<string>  返回 Base64(iv+cipher)
     decrypt,              // (base64IvAndCipher, base64Key) => Promise<string>
     saveKeyToLocalStorage,
     loadKeyFromLocalStorage
   };
 })();
export { SymmetricUtil };

//  export default SymmetricUtil;

 /*
 使用示例 (在 Vue 组件或其他模块中)：

 import SymmetricUtil from '@/utils/symmetric';

 // 生成密钥
 const key = await SymmetricUtil.generateKeyBase64();
 // key 是 Base64 字符串，可以传给后端或保存到 localStorage
 SymmetricUtil.saveKeyToLocalStorage('my_aes_key', key);

 // 加密
 const cipherBase64 = await SymmetricUtil.encrypt('hello world', key);

 // 解密
 const plain = await SymmetricUtil.decrypt(cipherBase64, key);

 注意：所有方法均为 Promise，请使用 await 或 then。
 */

